import tkinter as tk
from tkinter import filedialog, messagebox
from sqlalchemy import create_engine, MetaData
from docx import Document
from docx.shared import RGBColor
# 导出表格到 Word 文档
def export_table_to_word(document, table_name, fields_info):
    document.add_heading(f"Table: {table_name}", level=1)
    if fields_info:
        table = document.add_table(rows=1, cols=3)
        table.style = 'Table Grid'

        # 设置标题行文本颜色为商务灰色
        for cell in table.rows[0].cells:
            for paragraph in cell.paragraphs:
                for run in paragraph.runs:
                    run.font.color.rgb = RGBColor(79, 129, 189)  # 商务灰色的 RGB 颜色值

        hdr_cells = table.rows[0].cells
        hdr_cells[0].text = '表名称'
        hdr_cells[1].text = '数据类型'
        hdr_cells[2].text = '字段注释'

        for field in fields_info:
            row_cells = table.add_row().cells
            row_cells[0].text = field['name']
            row_cells[1].text = field['type']
            row_cells[2].text = field['comment'] or ''


# 数据库连接
def get_table_fields(ip, database, username, password):
    try:
        # 构建数据库连接字符串
        db_url = f"mysql://{username}:{password}@{ip}/{database}?charset=utf8mb4"
        # 创建数据库引擎
        engine = create_engine(db_url)
        # 创建元数据对象
        metadata = MetaData(bind=engine)
        # 反射表结构
        metadata.reflect()
        # 获取所有的表结构
        tables = metadata.tables
        return tables
    except Exception as e:
        return str(e)


# 获取所有的表对象
def get_all_table_structure(tables):
    # 定义所有表的结构信息字典
    all_tables_info = {}
    # 遍历所有表，获取所有表的结构
    for table_name, table in tables.items():
        table_info = []
        for column in table.columns:
            field_info = {
                "name": column.name,
                "type": str(column.type),
                "comment": column.comment if hasattr(column, 'comment') else None
            }
            table_info.append(field_info)
        all_tables_info[table_name] = table_info
    return all_tables_info


# 导出数据结构到 Word 文档
def export_to_word(ip, database, username, password, output_file_path):
    # 获取所有表的结构信息
    tables = get_table_fields(ip, database, username, password)
    if isinstance(tables, str):
        messagebox.showerror("Error", f"Database connection failed: {tables}")
        return

    all_tables_info = get_all_table_structure(tables)

    # 创建 Word 文档
    document = Document()
    for table_name, fields_info in all_tables_info.items():
        export_table_to_word(document, table_name, fields_info)

    output_file = output_file_path + "/数据库设计文档.docx"
    document.save(output_file)
    messagebox.showinfo("导出成功", f"数据库设计文档已经导出到 {output_file}")


# 创建主界面
# 创建主界面
def create_ui():
    window = tk.Tk()
    window.title("数据库表结构导出工具")
    # 设置窗口背景颜色为商务蓝色
    window.configure(bg="#ECF8FF")

    # 设置标签和输入框的间距
    padx, pady = 5, 5

    # 标签和输入框
    tk.Label(window, text="IP地址:").grid(row=0, column=0, sticky='E', padx=padx, pady=pady)
    ip_entry = tk.Entry(window)
    ip_entry.grid(row=0, column=1, padx=padx, pady=pady)

    tk.Label(window, text="数据库名称:").grid(row=1, column=0, sticky='E', padx=padx, pady=pady)
    database_entry = tk.Entry(window)
    database_entry.grid(row=1, column=1, padx=padx, pady=pady)

    tk.Label(window, text="用户名:").grid(row=2, column=0, sticky='E', padx=padx, pady=pady)
    username_entry = tk.Entry(window)
    username_entry.grid(row=2, column=1, padx=padx, pady=pady)

    tk.Label(window, text="密码:").grid(row=3, column=0, sticky='E', padx=padx, pady=pady)
    password_entry = tk.Entry(window, show="*")
    password_entry.grid(row=3, column=1, padx=padx, pady=pady)

    tk.Label(window, text="文件存储路径:").grid(row=4, column=0, sticky='E', padx=padx, pady=pady)
    output_path_entry = tk.Entry(window, state="readonly")
    output_path_entry.grid(row=4, column=1, padx=padx, pady=pady)

    # 选择文件存储路径的按钮
    def select_output_path():
        output_path = filedialog.askdirectory()
        output_path_entry.configure(state="normal")
        output_path_entry.delete(0, tk.END)
        output_path_entry.insert(0, output_path)
        output_path_entry.configure(state="readonly")

    tk.Button(window, text="选择路径", command=select_output_path).grid(row=4, column=2, padx=padx, pady=pady)

    # 测试连接的按钮
    def test_connection():
        ip = ip_entry.get()
        database = database_entry.get()
        username = username_entry.get()
        password = password_entry.get()
        try:
            engine = create_engine(f"mysql://{username}:{password}@{ip}/{database}?charset=utf8mb4")
            connection = engine.connect()
            messagebox.showinfo("Success", "数据库连接成功！")
            connection.close()
        except Exception as e:
            messagebox.showerror("Error", f"数据库连接失败: {str(e)}")

    # 导出按钮
    def export():
        ip = ip_entry.get()
        database = database_entry.get()
        username = username_entry.get()
        password = password_entry.get()
        output_path = output_path_entry.get()
        export_to_word(ip, database, username, password, output_path)

    # 测试连接按钮
    tk.Button(window, text="测试连接", command=test_connection).grid(row=5, column=0, padx=10, pady=10, columnspan=2)
    # 导出按钮
    tk.Button(window, text="导出文档", command=export).grid(row=5, column=1, pady=10, columnspan=8)

    # 将窗口移动到屏幕中心
    window.update_idletasks()  # 确保窗口的几何属性已被更新
    width = window.winfo_width()  # 获取窗口宽度
    height = window.winfo_height()  # 获取窗口高度
    x_offset = (window.winfo_screenwidth() - width) // 2  # 计算窗口左上角 x 坐标偏移量
    y_offset = (window.winfo_screenheight() - height) // 2  # 计算窗口左上角 y 坐标偏移量
    window.geometry(f"+{x_offset}+{y_offset}")  # 将窗口移动到屏幕中心

    window.mainloop()


# 运行主界面
if __name__ == "__main__":
    create_ui()
